from fastapi.encoders import jsonable_encoder
from fastapi.responses import UJSONResponse
from fastapi import status

from common.g.g import G_SETTINGS
from common.config.settings import EnvEnum

__all__ = ["JsonResponse", "RC"]


class RC:
    SUCCESS = 0

    ADD_LOCK_FAIL = 200_100_00  # 加锁失败
    QUANTITY_NOT_ENOUGH = 200_200_00  # mall 商品库存不足

    PARAM_ERROR = 400_000_00
    PARAM_MISSING = 400_000_01
    LANGUAGE_ALREADY_EXIST = 400_101_00  # 语言已经存在
    CURRENCY_ALREADY_EXIST = 400_102_00  # 币种已经存在
    ATTRIBUTE_ALREADY_EXIST = 400_103_00  # 属性已经存在
    SLUG_ALREADY_EXIST = 400_104_00  # 二级域名已经存在
    PHONE_ALREADY_REGISTER = 400_105_00  # 手机号已经注册
    EMAIL_ALREADY_REGISTER = 400_106_00  # 邮箱已经注册

    AUTH_FAILED = 401_000_00
    AUTH_ERROR = 401_000_01
    TOKEN_EXPIRE = 401_000_02
    NEED_LOGIN_TENANT = 401_100_03  # 需要选择租户登陆
    NEED_RELOGIN_TENANT = 401_100_04  # 需要重新登陆

    FORBIDDING = 403_000_00
    RATE_LIMIT = 403_100_01  # 请求太频繁
    RESET_RESOURCE = 403_100_02  # 重复设置资源信息

    NOT_EXIST = 404_000_00  # 404
    TENANT_NOT_EXIST = 404_100_00  # tenant不存在
    LANGUAGE_NOT_EXIST = 404_101_00  # 语言不存在
    CURRENCY_NOT_EXIST = 404_102_00  # 币种不存在
    PAYWAY_NOT_EXIST = 404_100_03  # 支付方式不存在
    ATTRIBUTE_NOT_EXIST = 404_104_00  # 属性不存在
    INVITE_CODE_NOT_EXIST = 404_100_05  # 邀请码无效
    MALL_NOT_EXIST = 404_110_01  # mall不存在
    USER_NOT_EXIST = 404_200_00  # 用户不存在

    PART_NOT_EXIST = 404_000_01
    LOGIN_FAILED = 404_000_01

    INTER_ERROR = 500_000_00
    REGISTER_TENANT_FAIL = 500_100_00  # 注册租户失败
    DB_ERROR = 500_500_00  # 数据库访问出错
    REDIS_ERROR = 500_500_01  # redis访问出错


class ERROR:
    REPEAT_EXCEPTION = 1  # 唯一异常

    # 大于0是正常的错误，但是不应该报错，小于0是异常的，应该报错

    REPEAT_ERROR = -1  # 唯一错误
    DB_ERROR = -2  # 数据库异常
    REDIS_ERROR = -3  # redis异常


class JsonResponse:

    def __init__(self, code=RC.SUCCESS, msg='', data=None, exception_track=None, response_model=None):
        self._code = code
        self._msg = msg
        self._data = data
        self._exception_track = exception_track
        self._response_model = response_model

    @property
    def status_code(self):
        if self._code < 0:
            return status.HTTP_500_INTERNAL_SERVER_ERROR
        if self._code < 100_000_00:
            return status.HTTP_200_OK
        if self._code < 400_000_00:
            return status.HTTP_200_OK
        else:
            return self._code // 100_000

    def _to_dict(self):
        if self._response_model:
            _d = jsonable_encoder(self._response_model(self._data).dict())
        else:
            _d = jsonable_encoder(self._data)
        base_data = {
            "code": self._code,
            "msg": self._msg,
            "data": _d
        }
        if G_SETTINGS.env in (EnvEnum.local, EnvEnum.dev, EnvEnum.test):
            base_data["exception"] = jsonable_encoder(self._exception_track)
        return base_data

    def to_response(self):
        return UJSONResponse(content=self._to_dict(), status_code=self.status_code)

    @classmethod
    def not_found(cls, msg: str = None):
        return cls(code=RC.NOT_EXIST, msg=msg or "资源不存在").to_response()

    @classmethod
    def inner_error(cls, msg: str = None, exception_track=None):
        return cls(code=RC.INTER_ERROR, msg=msg or "服务器错误,请稍后重试", exception_track=exception_track).to_response()